#include "OptData.h"

OptData::OptData(void)
{
	this->m_nSizeX=0;
	this->m_nSizeY=0;
	this->m_nSizeZ=0;
	this->m_nBeamletNumTotal=0;
	//this->m_nWeightNumTotal=0;
}
OptData::OptData(const OptData &obj)
{
	this->m_nSizeX=obj.m_nSizeX;
	this->m_nSizeY=obj.m_nSizeY;
	this->m_nSizeZ=obj.m_nSizeZ;
	this->m_nBeamletNumTotal=obj.m_nBeamletNumTotal;
	//this->m_nWeightNumTotal=obj.m_nWeightNumTotal;
	this->m_vFieldBeamletNum=obj.m_vFieldBeamletNum;
	this->m_vStructures = obj.m_vStructures;
	this->m_vDijIndex = obj.m_vDijIndex;
	this->m_vDijTotal = obj.m_vDijTotal;
	this->m_vWeightTotal = obj.m_vWeightTotal;
	this->m_vEUD = obj.m_vEUD;
	this->m_vObjs = obj.m_vObjs;
}
OptData::~OptData(void)
{
}
OptData& OptData::operator = (OptData& obj)
{
	this->m_nSizeX=obj.m_nSizeX;
	this->m_nSizeY=obj.m_nSizeY;
	this->m_nSizeZ=obj.m_nSizeZ;
	this->m_nBeamletNumTotal=obj.m_nBeamletNumTotal;
	//this->m_nWeightNumTotal=obj.m_nWeightNumTotal;
	this->m_vFieldBeamletNum=obj.m_vFieldBeamletNum;
	this->m_vStructures = obj.m_vStructures;
	this->m_vDijIndex = obj.m_vDijIndex;
	this->m_vDijTotal = obj.m_vDijTotal;
	this->m_vWeightTotal = obj.m_vWeightTotal;
	this->m_vEUD = obj.m_vEUD;
	this->m_vObjs = obj.m_vObjs;
	return *this;
}

bool OptData::calculateDose(void)
{
#ifdef USE_OMP
#pragma omp parallel for
#endif
	for(int i=0;i<m_vDose.size();i++){
		m_vDose[i]=0;
	}

	this->m_vDose.resize(m_vDijTotal.size(),0);

	int indexPoint=0;
	int indexBeamlet;
#ifdef USE_OMP
#pragma omp parallel for default(shared) private(indexPoint,indexBeamlet) schedule(dynamic)
#endif
	for(indexPoint = 0; indexPoint<m_vDijTotal.size(); indexPoint++)
	{
		double contriTemp = 0;
		double weiTemp = 0;
		for(indexBeamlet = 0; indexBeamlet < (m_vDijTotal)[indexPoint].size();indexBeamlet++)
		{
			contriTemp = (m_vDijTotal)[indexPoint][indexBeamlet];

			weiTemp = (m_vWeightTotal)[indexBeamlet];

			//if contribution = 0 or weight =0 do not calculate
			if(!(((contriTemp >= -0.00000001)&&(contriTemp <= 0.00000001))||((weiTemp >= -0.00000001)&&(weiTemp <= 0.00000001))))
			{
				this->m_vDose[indexPoint] += contriTemp*weiTemp;
			}
		}
	}
	return true;
}

bool OptData::calculateEUD(void){
	if(m_vDose.size()==0 || m_vStructures.size()==0){
		cout<<"There is no dose or structures!"<<endl;
		return false;
	}
	for(int index=0;index<m_vStructures.size();index++){
		double doseTotal = 0;
		int indexPoint = 0;
#ifdef USE_OMP
#pragma omp parallel for default(shared) reduction(+:doseTotal) private(indexPoint)
#endif
		for (indexPoint = 0; indexPoint < m_vStructures[index].getPoints()->size(); indexPoint++) {
			doseTotal += pow(m_vDose[(*m_vStructures[index].getPoints())[indexPoint]],m_vStructures[index].getEUDfac());
		}
		double eud = pow(doseTotal/(*m_vStructures[index].getPoints()).size(),1/m_vStructures[index].getEUDfac());
		this->m_vEUD.push_back(eud);
	}
	return true;
}

vector<double>  OptData::calculateDVH(Structure structure,double dvhResolution)
{
	double maxDose=0;
	for(int i=0;i<m_vDose.size();i++)
	{
		if(maxDose < (m_vDose)[i])
		{
			maxDose = (m_vDose)[i];
		}
	}
	int size = (int)(maxDose/dvhResolution +1);

	vector<double> result;
	result.resize(size);

	for (int j = 0; j < structure.getPoints()->size(); j++) {
		double dose = (m_vDose)[(*structure.getPoints())[j]];
		int doseT = (int)(dose/dvhResolution);
		for(int index=0;index<=doseT;index++){
			result[index]=result[index]+1;
		}
	}
	for (int j = 0; j < result.size(); j++) {

		result[j]=result[j]/structure.getPoints()->size();

	}
	return result;
}

bool OptData::inputDoseSize(string inDoseSizePath)
{
	path pathInput(inDoseSizePath);
	ifstream ifs;
	string line;

	try{
		if(!exists(pathInput)){
			cout<<"input file "<<inDoseSizePath<<" error!"<<endl;
			return false;
		}

		ifs.open(pathInput.native_file_string().c_str());
		if(ifs.is_open())
		{
			getline(ifs,line);
			if(line.length()>0)
			{
				std::replace(line.begin(), line.end(), '.', ',');
				vector<string> vstrings;
				boost::split(vstrings,line,boost::is_any_of(","));
				if(vstrings.size()==3)
				{
					this->setDoseMatrixSize(
						atoi(vstrings[0].c_str()),  //x
						atoi(vstrings[1].c_str()),  //y
						atoi(vstrings[2].c_str())   //z
						);
				}
			}
		}
		else
		{
			throw runtime_error(inDoseSizePath + " file open error");
		}
		ifs.close();
		ifs.clear();
		return true;
	}
	catch(const filesystem_error& ex){
		ifs.close();
		ifs.clear();
		cout<<ex.what()<<endl;
		return false;
	}

	
}

bool OptData::inputBeamType1(int fieldID, string inDijPath, string inSpotWeightPath){

	path pathInputDij(inDijPath);
	path pathInputWeight(inSpotWeightPath);
	if((!exists(pathInputDij))||(!exists(pathInputWeight))){
		cout<<"input beam file error!"<<endl;
		return false;
	}
	
	ifstream ifsDijFile;
	ifstream ifsWeightFile;
	string line;

	if((this->m_vDijTotal.size())!=(m_nSizeX*m_nSizeY*m_nSizeZ))
	{
		this->m_vDijTotal.resize(m_nSizeX*m_nSizeY*m_nSizeZ);
	}
	int baseBeamletNum = this->m_nBeamletNumTotal;
	int beamletNumField = 0;
	//read Weight File
	ifsWeightFile.open(pathInputWeight.native_file_string().c_str());
	if(ifsWeightFile.is_open())
	{
		getline(ifsWeightFile,line);
		beamletNumField = atoi(line.c_str());
		this->m_vFieldBeamletNum.push_back(beamletNumField);
		while(getline(ifsWeightFile,line))
		{
			if(line.length()>0)
			{
				vector<string> vsWeightLine;
				boost::split(vsWeightLine,line,boost::is_any_of(","));
				if(vsWeightLine.size()==2)
				{
					this->m_vWeightTotal.push_back(atof(vsWeightLine[1].c_str()));
				}
				else
				{
					throw runtime_error("weight file error!");
					return false;
				}
			}
		}
	}
	else
	{
		throw runtime_error(inSpotWeightPath + " file open error");
		return false;
	}

	this->m_nBeamletNumTotal += beamletNumField;

	try{
		unsigned int sizeX,sizeY,sizeZ;
		this->getDoseMatrixSize(sizeX,sizeY,sizeZ);
		if(sizeX == 0 || sizeY == 0 || sizeZ == 0)
		{
			throw runtime_error("Dose matrix size is needed to be read first!");
			return false;
		}

		//read SpotField File

		ifsDijFile.open(pathInputDij.native_file_string().c_str());
		if(ifsDijFile.is_open())
		{
			getline(ifsDijFile,line);
			while(getline(ifsDijFile,line))
			{
				if(line.length()>0)
				{
					vector<string> vsDijLine;
					boost::split(vsDijLine,line,boost::is_any_of(","));
					if(vsDijLine.size()==5)
					{
						double contri = atof(vsDijLine[4].c_str());

						int point = this->position3DTo1D(atoi(vsDijLine[0].c_str()),
							atoi(vsDijLine[1].c_str()),atoi(vsDijLine[2].c_str()));

						int beamletID = atoi(vsDijLine[3].c_str());

						if((m_vDijTotal)[point].size() != this->m_nBeamletNumTotal){
							(m_vDijTotal)[point].resize(this->m_nBeamletNumTotal);
						}
						(m_vDijTotal)[point][beamletID + baseBeamletNum] = contri;
					}
					else
					{
						cout<<line<<endl;
						throw runtime_error("field file error!");
						return false;
					}
				}
			}
		}
		else
		{
			throw runtime_error(inDijPath + " file open error");
			return false;
		}

		ifsDijFile.close();
		ifsWeightFile.close();

		return true;

	}
	catch(exception ex)
	{
		ifsDijFile.close();
		ifsDijFile.clear();
		ifsWeightFile.close();
		ifsWeightFile.clear();

		cerr<<ex.what()<<endl;
		return false;
	}
}

bool OptData::inputBeamType2(int fieldID, string inDijPath, string inSpotWeightPath){

	path pathInputDij(inDijPath);
	path pathInputWeight(inSpotWeightPath);
	if((!exists(pathInputDij))||(!exists(pathInputWeight))){
		cout<<"input beam file error!"<<endl;
		return false;
	}

	ifstream ifsDijFile;
	ifstream ifsWeightFile;
	string line;

	if((this->m_vDijTotal.size())!=(m_nSizeX*m_nSizeY*m_nSizeZ))
	{
		this->m_vDijTotal.resize(m_nSizeX*m_nSizeY*m_nSizeZ);
	}
	int baseBeamletNum = this->m_nBeamletNumTotal;
	int beamletNumField = 0;
	//read Weight File
	ifsWeightFile.open(pathInputWeight.native_file_string().c_str());
	if(ifsWeightFile.is_open())
	{
		getline(ifsWeightFile,line);
		beamletNumField = atoi(line.c_str());
		this->m_vFieldBeamletNum.push_back(beamletNumField);
		while(getline(ifsWeightFile,line))
		{
			if(line.length()>0)
			{
				vector<string> vsWeightLine;
				boost::split(vsWeightLine,line,boost::is_any_of(","));
				if(vsWeightLine.size()==2)
				{
					this->m_vWeightTotal.push_back(atof(vsWeightLine[1].c_str()));
				}
				else
				{
					throw runtime_error("weight file error!");
					return false;
				}
			}
		}
	}
	else
	{
		throw runtime_error(inSpotWeightPath + " file open error");
		return false;
	}

	this->m_nBeamletNumTotal += beamletNumField;

	try{
		unsigned int sizeX,sizeY,sizeZ;
		this->getDoseMatrixSize(sizeX,sizeY,sizeZ);
		if(sizeX == 0 || sizeY == 0 || sizeZ == 0)
		{
			throw runtime_error("Dose matrix size is needed to be read first!");
			return false;
		}

		//read SpotField File
		ifsDijFile.open(pathInputDij.native_file_string().c_str());
		if(ifsDijFile.is_open())
		{
			while(getline(ifsDijFile,line))
			{
				if(line.length()>0)
				{
					vector<string> vsDijLine;
					boost::split(vsDijLine,line,boost::is_any_of(","));
					if(vsDijLine.size()==2)
					{
						double contri = atof(vsDijLine[1].c_str());

						vector<string> vsFieldSubLine;
						boost::split(vsFieldSubLine,vsDijLine[0],boost::is_any_of("."));

						if(vsFieldSubLine.size()==5)
						{
							int point = this->position3DTo1D(atoi(vsFieldSubLine[0].c_str()),
								atoi(vsFieldSubLine[1].c_str()),atoi(vsFieldSubLine[2].c_str()));

							int beamletID = atoi(vsFieldSubLine[4].c_str());

							if((m_vDijTotal)[point].size() != this->m_nBeamletNumTotal){
								(m_vDijTotal)[point].resize(this->m_nBeamletNumTotal);
							}
							(m_vDijTotal)[point][beamletID + baseBeamletNum] = contri;
						}
						else
						{
							throw runtime_error("field file error!");
							return false;
						}
					}
					else
					{
						throw runtime_error("field file error!");
						return false;
					}
				}
			}
		}
		else
		{
			throw runtime_error(inDijPath + " file open error");
			return false;
		}

		ifsDijFile.close();
		ifsWeightFile.close();
		return true;
	}
	catch(exception ex)
	{
		ifsDijFile.close();
		ifsDijFile.clear();
		ifsWeightFile.close();
		ifsWeightFile.clear();

		cerr<<ex.what()<<endl;
		return false;
	}
}

bool OptData::inputBeamFromBin(int fieldID, string inDijPath, string inSpotWeightPath)
{

	path pathInputDij(inDijPath);
	path pathInputWeight(inSpotWeightPath);
	if((!exists(pathInputDij))||(!exists(pathInputWeight))){
		cout<<"input beam file error!"<<endl;
		return false;
	}

	ifstream ifsDijFile;
	ifstream ifsWeightFile;
	string line;

	if((this->m_vDijTotal.size())!=(m_nSizeX*m_nSizeY*m_nSizeZ))
	{
		this->m_vDijTotal.resize(m_nSizeX*m_nSizeY*m_nSizeZ);
	}
	int baseBeamletNum = this->m_nBeamletNumTotal;
	int beamletNumField = 0;
	//read Weight File
	try{
		ifsWeightFile.open(pathInputWeight.native_file_string().c_str());
		if(ifsWeightFile.is_open())
		{
			getline(ifsWeightFile,line);
			beamletNumField = atoi(line.c_str());
			this->m_vFieldBeamletNum.push_back(beamletNumField);
			while(getline(ifsWeightFile,line))
			{
				if(line.length()>0)
				{
					vector<string> vsWeightLine;
					boost::split(vsWeightLine,line,boost::is_any_of(","));
					if(vsWeightLine.size()==2)
					{
						this->m_vWeightTotal.push_back(atof(vsWeightLine[1].c_str()));
					}
					else
					{
						throw runtime_error("weight file error!");
						return false;
					}
				}
			}
		}
		else
		{
			throw runtime_error(inSpotWeightPath + " file open error");
			return false;
		}

		this->m_nBeamletNumTotal += beamletNumField;

		//read Contri File
		unsigned int sizeX,sizeY,sizeZ;
		this->getDoseMatrixSize(sizeX,sizeY,sizeZ);
		if(sizeX == 0 || sizeY == 0 || sizeZ == 0)
		{
			throw runtime_error("Dose matrix size is needed to be read first!");
			return false;
		}

		//read SpotField binary File
		ifsDijFile.open(pathInputDij.native_file_string().c_str(),ios::in|ios::binary);
		if(!ifsDijFile.is_open())
		{
			cerr<<"ERROR opening the spot contribution file to read: "<<pathInputDij.native_file_string()<<endl; 
			return false;
		}

		int nx, ny, nz, nSpotCachedPerVox;
		ifsDijFile.read((char*)&nx, sizeof(int));
		ifsDijFile.read((char*)&ny, sizeof(int));
		ifsDijFile.read((char*)&nz, sizeof(int));
		if(sizeX != nx || sizeY != ny || sizeZ != nz) {
			cerr << "Error: The binary cache file does not match the Scan Ion Control Point Sequence" << endl;
			return false;
		}

		int nRCursor  = 0;
		while(!ifsDijFile.eof() && nRCursor < sizeX * sizeY * sizeZ) {
			ifsDijFile.read((char*)&nx, sizeof(int));
			ifsDijFile.read((char*)&ny, sizeof(int));
			ifsDijFile.read((char*)&nz, sizeof(int));
			if(nx >= sizeX || ny >= sizeY || nz >= sizeZ) {
				cerr << "Error: the dose voxel index input from the file is out of range: (" << nx << ", " << ny << ", " << nz << ")" << endl;
				//return false;
				continue;
			}

			ifsDijFile.read((char*)&nSpotCachedPerVox, sizeof(int));
			if(nSpotCachedPerVox<=0) continue;

			int point = this->position3DTo1D(nx,ny,nz);
			if((m_vDijTotal)[point].size() != this->m_nBeamletNumTotal){
				(m_vDijTotal)[point].resize(this->m_nBeamletNumTotal);
			}
			INFLU_ELEM *arrInfluElems = new INFLU_ELEM[nSpotCachedPerVox];
			ifsDijFile.read(reinterpret_cast<char*>(arrInfluElems), sizeof(INFLU_ELEM)*nSpotCachedPerVox);

			for(int ispt = 0; ispt<nSpotCachedPerVox;ispt++){
				long nSpotID = arrInfluElems[ispt].m_nID;
				float fContrib = arrInfluElems[ispt].m_fContrib;

				if((nSpotID)>this->m_nBeamletNumTotal){
					cerr << "Error: the beamlet index input from the file is out of range: (" << nSpotID << ")" <<" Total = " << this->m_nBeamletNumTotal << endl;
					cerr << nRCursor <<endl;
					//return false;
					continue;
				}

				(m_vDijTotal)[point][nSpotID] = fContrib;
			}

			delete [] arrInfluElems;
			nRCursor++;
		}
		ifsDijFile.close();
		ifsWeightFile.close();
		return true;
	}catch(exception ex)
	{
		ifsDijFile.close();
		ifsDijFile.clear();
		ifsWeightFile.close();
		ifsWeightFile.clear();

		cerr<<ex.what()<<endl;
		return false;
	}
}

bool OptData::inputBeam(int BeamID, string inDijPath, string inSpotWeightPath){

	path pathInputDij(inDijPath);
	path pathInputWeight(inSpotWeightPath);
	if((!exists(pathInputDij))||(!exists(pathInputWeight))){
		cout<<"input beam file error!"<<endl;
		return false;
	}


	ifstream ifsDijFile;
	string line;
	ifsDijFile.open(pathInputDij.native_file_string().c_str());
	if(int pos = inDijPath.find("cabin") != string::npos){
		inputBeamFromBin(BeamID, inDijPath, inSpotWeightPath);
	}
	else if(ifsDijFile.is_open())
	{
		getline(ifsDijFile,line);
		if(line.length()>0)
		{
			vector<string> vsDijLine;
			boost::split(vsDijLine,line,boost::is_any_of(","));
			if(vsDijLine.size()==3)
			{
				inputBeamType1(BeamID, inDijPath, inSpotWeightPath);
			}
			else
			{
				inputBeamType2(BeamID, inDijPath, inSpotWeightPath);
			}
		}
	}
	else
	{
		throw runtime_error(inDijPath + " file open error");
		return false;
	}

	ifsDijFile.close();
	return true;
}

bool OptData::inputStructure(string structName, string inStructPath,double EUD){
	path pathInputStructure(inStructPath);

	if(!exists(pathInputStructure)){
		cout<<"input structure file error!"<<endl;
		return false;
	}

	ifstream ifs;
	string line;

	Structure pStruct;
	//vector<int> vPoints = pStruct->getPoints();
	pStruct.setStructName(structName);
	pStruct.setEUDfactor(EUD);

	unsigned int x,y,z;
	this->getDoseMatrixSize(x,y,z);
	try{

		ifs.open(pathInputStructure.native_directory_string().c_str());
		if(ifs.is_open())
		{
			while(getline(ifs,line))
			{
				if(line.length()>0)
				{
					std::replace(line.begin(), line.end(), '.', ',');
					vector<string> vstrings;
					boost::split(vstrings,line,boost::is_any_of(","));
					if(vstrings.size()==3)
					{

						int positionTemp = 0;

						if((atoi(vstrings[0].c_str())<x)&&(atoi(vstrings[1].c_str())<y)&&(atoi(vstrings[2].c_str())<z))
						{
							positionTemp = this->position3DTo1D(atoi(vstrings[0].c_str()),
								atoi(vstrings[1].c_str()),atoi(vstrings[2].c_str()));

							pStruct.getPoints()->push_back(positionTemp);
							//vPoints->push_back(positionTemp);
						}
					}
				}
			}
		}
		else
		{
			throw runtime_error(pathInputStructure.native_directory_string() + " file open error");
			return false;
		}

		// add structure to matrix
		this->addStructure(pStruct);

		//delete pStruct;
		ifs.close();
		ifs.clear();
		return true;
	}
	catch(exception ex)
	{
		ifs.close();
		ifs.clear();

		//delete pStruct;
		cerr<<ex.what()<<endl;
		return false;
	}
}

bool OptData::inputObjective(string objString){
	RadiationObj obj;
	vector<string> strs;
	boost::split(strs,objString,boost::is_any_of(","));
	obj.strStructureName = strs[0];
	obj.constraintType=strs[1];
	obj.aimDose=atof(strs[2].c_str());
	obj.aimWeight=atof(strs[3].c_str());
	this->m_vObjs.push_back(obj);
	return true;
}

bool OptData::inputDose(string inDosePath){
	path pathInputDose(inDosePath);

	if(!exists(pathInputDose)){
		cout<<"input structure file error!"<<endl;
		return false;
	}

	ifstream ifs;
	string line;

	try{

		ifs.open(pathInputDose.native_file_string().c_str());
		if(ifs.is_open())
		{
			while(getline(ifs,line))
			{
				if(line.length()>0)
				{
					vector<string> vstrings;
					boost::split(vstrings,line,boost::is_any_of(","));
					if(vstrings.size()>1){
						for(int i=0;i<vstrings.size();i++){
							m_vDose.push_back(atof(vstrings[i].c_str()));
						}
					}

				}
			}
		}
		else
		{
			throw runtime_error(inDosePath + " file open error");
			return false;
		}

		ifs.close();
		ifs.clear();
		return true;
	}
	catch(exception ex)
	{
		ifs.close();
		ifs.clear();

		//delete pStruct;
		cerr<<ex.what()<<endl;
		return false;
	}
}

bool OptData::outputWeight(string outputDir){

	path pathOutput(outputDir);
	ofstream ofs;
	try{
		if(!exists(pathOutput)){
			create_directory(pathOutput);
		}
		if (exists(pathOutput))    // does p actually exist?
		{
			if (is_directory(pathOutput))      // is p a directory?
			{
				
				for(int indexOfField=0;indexOfField<this->m_vFieldBeamletNum.size();indexOfField++){
					//calculate offset
					int offset = 0;
					for(int indexOffset = 0; indexOffset < indexOfField; indexOffset ++)
					{
						offset += m_vFieldBeamletNum[indexOffset];
					}
					int endPoint = m_vFieldBeamletNum[indexOfField]+offset;

					std::stringstream pathBuff;
					//pathBuff.str("");
					pathBuff << "resultWeight_" << indexOfField+1 << ".txt";
					string strWtFullPath = (pathOutput/path(pathBuff.str())).string();
					ofs.open(strWtFullPath.c_str());
					//cout<<strWtFullPath.c_str()<<endl;
					if(ofs.is_open())
					{
						ofs<<endPoint-offset<<endl;
						for(int indexInTotalWeight=offset; indexInTotalWeight<endPoint;indexInTotalWeight++)
						{
							ofs<<indexInTotalWeight-offset<<","<<(m_vWeightTotal)[indexInTotalWeight]<<endl;
						}
					}

					ofs.close();

				}
				return true;
			}
			else{
				cout << pathOutput << " exists, but is neither a regular file nor a directory\n";
				return false;
			}
		}
		else
		{
			cout << pathOutput << " does not exist\n";
			return false;
		}
	}
	catch(const filesystem_error& ex){
		ofs.close();
		cout<<ex.what()<<endl;
		return false;
	}
}

bool OptData::outputDij(string outputDir)
{
	path pathOutput(outputDir);
	ofstream ofs;
	try{
		if(!exists(pathOutput)){
			create_directory(pathOutput);
		}
		if (exists(pathOutput))    // does p actually exist?
		{
			if (is_directory(pathOutput))      // is p a directory?
			{
				std::stringstream pathBuff;
				//pathBuff.str("");
				pathBuff << "resultDij.txt";
				string strDijFullPath = (pathOutput/path(pathBuff.str())).string();
				ofs.open(strDijFullPath.c_str());
				//cout<<strWtFullPath.c_str()<<endl;
				if(ofs.is_open())
				for(int indexVDij = 0; indexVDij != m_vDijTotal.size(); indexVDij ++)
				{
					for(int indexDij = 0; indexDij != (m_vDijTotal)[indexVDij].size(); indexDij++)
					{
						ofs<<(m_vDijTotal)[indexVDij][indexDij]<<" ";
					}
					ofs<<endl;
				}
				ofs.close();
				return true;
			}
			else{
				cout << pathOutput << " exists, but is neither a regular file nor a directory\n";
				return false;
			}
		}
		else
		{
			cout << pathOutput << " does not exist\n";
			return false;
		}
	}
	catch(const filesystem_error& ex){
		cout<<ex.what()<<endl;
		return false;
	}
}

bool OptData::outputDose(string outputDir)
{

	path pathOutput(outputDir);
	try{
		if(!exists(pathOutput)){
			create_directory(pathOutput);
		}
		if (exists(pathOutput))    // does p actually exist?
		{
			if (is_directory(pathOutput))      // is p a directory?
			{
				ofstream ofs;

				std::stringstream pathBuff;
				//pathBuff.str("");
				pathBuff << "resultDose.txt";
				string strDoseFullPath = (pathOutput/path(pathBuff.str())).string();
				ofs.open(strDoseFullPath.c_str());
				//cout<<strWtFullPath.c_str()<<endl;
				if(ofs.is_open())
				{
					ofs<<endl;
					ofs<<"#0"<<endl;
					for(int i=0;i<m_vDose.size();i++)
					{
						ofs<<(m_vDose)[i]<<" ";
						if((i!=0) && (i!=m_vDose.size()-1) && ((i+1)%m_nSizeX)==0)
						{
							ofs<<endl;
						}
						if((i!=0) &&(i!=m_vDose.size()-1) &&((i+1)%(m_nSizeY*m_nSizeX))==0)
						{
							ofs<<endl;
							ofs<<"#"<<((i+1)/(m_nSizeY*m_nSizeX))<<endl;
						}
					}
				}

				ofs.close();
				ofs.clear();
				return true;
			}
			else{
				cout << pathOutput << " exists, but is neither a regular file nor a directory\n";
				return false;
			}
		}
	}
	catch(const filesystem_error& ex){
		cout<<ex.what()<<endl;
		return false;
	}
}

bool OptData::outputObjValue(string outputDir)
{

	path pathOutput(outputDir);
	try{
		if(!exists(pathOutput)){
			create_directory(pathOutput);
		}
		if (exists(pathOutput))    // does p actually exist?
		{
			if (is_directory(pathOutput))      // is p a directory?
			{
				ofstream ofs;

				std::stringstream pathBuff;
				//pathBuff.str("");
				pathBuff << "objValue.txt";
				string strObjFunValueFullPath = (pathOutput/path(pathBuff.str())).string();
				ofs.open(strObjFunValueFullPath.c_str());
				//cout<<strWtFullPath.c_str()<<endl;
				if(ofs.is_open())
				{

					for(int i=0;i<m_vObjFunValues.size();i++)
					{
						ofs<<(m_vObjFunValues)[i]<<endl;
					}
				}

				ofs.close();
				ofs.clear();
				return true;
			}
			else{
				cout << pathOutput << " exists, but is neither a regular file nor a directory\n";
				return false;
			}
		}
	}
	catch(const filesystem_error& ex){
		cout<<ex.what()<<endl;
		return false;
	}
}

bool OptData::outputDVH(string outputDir,double dvhResolution)
{
	path pathOutput(outputDir);
	try{
		if(!exists(pathOutput)){
			create_directory(pathOutput);
		}

		if (exists(pathOutput))    // does p actually exist?
		{
			if (is_directory(pathOutput))      // is p a directory?
			{
				ofstream ofs;

				vector<vector<double> > dvhs;
				int maxDVHSize=0;
				//pathBuff.str("");
				for(int index=0; index<m_vStructures.size();index++){
					std::stringstream pathBuff;
					pathBuff << m_vStructures[index].getStructName()<<".dvh";
					string strDoseFullPath = (pathOutput/path(pathBuff.str())).string();
					ofs.open(strDoseFullPath.c_str());

					vector<double> dvh = calculateDVH(m_vStructures[index],dvhResolution);
					cout<<m_vStructures[index].getStructName()<<" "<<dvh.size()<<endl;
					 
					dvhs.push_back(dvh);
					maxDVHSize = (maxDVHSize<dvh.size())?dvh.size():maxDVHSize;
					

					for(int i=0;i<dvh.size();i++){
						if(dvh[i]!=0){
							ofs<<(double)i*dvhResolution<<"\t"<<dvh[i]<<endl;
						}
					}
					ofs.close();
					ofs.clear();
					
				}		

				cout<<maxDVHSize<<endl;
				for(int index=0; index<m_vStructures.size();index++){
					dvhs[index].resize(maxDVHSize,0);
				}
				
				std::stringstream pathBuff;
				pathBuff << "total.dvh";
				string strDoseFullPath = (pathOutput/path(pathBuff.str())).string();
				ofs.open(strDoseFullPath.c_str());

				ofs<<"dose"<<"\t";
				for(int index=0; index<m_vStructures.size();index++){
					ofs<<m_vStructures[index].getStructName()<<"\t";
				}
				ofs<<endl;

				for(int i=0;i<maxDVHSize;i++){
					ofs<<(double)i*dvhResolution<<"\t";
					for(int idvh=0;idvh<dvhs.size();idvh++){
						ofs<<dvhs[idvh][i]<<"\t";
					}
					ofs<<endl;
				}
				ofs.close();
				ofs.clear();
				return true;
			}
			else{
				cout << pathOutput << " exists, but is neither a regular file nor a directory\n";
				return false;
			}
		}
	}
	catch(const filesystem_error& ex){
		cout<<ex.what()<<endl;
		return false;
	}
}

